Imports Aricie.DNN.Caching
Imports Aricie.Collections
Imports System.ComponentModel
Imports Aricie.DNN.UI.Attributes
Imports Aricie.DNN
Imports Aricie.ComponentModel
Imports DotNetNuke.UI.WebControls
Imports Aricie.DNN.Caching.Analysis.Graphs
Imports Aricie.DNN.UI.WebControls.EditControls
Imports QuickGraph

Namespace Aricie.DNN.Caching.Analysis
    <Serializable()> _
    Public Class CacheStatistics

        Private _ComputationDate As Date = Now

        'Private _LastLogTime As DateTime = DateTime.MinValue

        Private _GeneratedBy As String = ""

        Private _ComputationTime As New STimeSpan(TimeSpan.Zero)

        Private _NbEventLogs As Integer

        Private _StatisticsGraph As DistributedCachingGraph

        Private _AverageKeyStatistics As New CacheKeyStatistics

        Private _StatsByKey As New SerializableDictionary(Of String, CacheKeyStatistics)


        <ExtendedCategory("MetaData")> _
            <MainCategory()> _
            <IsReadOnly(True)> _
        Public Property ComputationDate() As Date
            Get
                Return _ComputationDate
            End Get
            Set(ByVal value As Date)
                _ComputationDate = value
            End Set
        End Property

        <ExtendedCategory("MetaData")> _
            <IsReadOnly(True)> _
        Public Property GeneratedBy() As String
            Get
                Return _GeneratedBy
            End Get
            Set(ByVal value As String)
                _GeneratedBy = value
            End Set
        End Property

        <ExtendedCategory("MetaData")> _
            <IsReadOnly(True)> _
        Public Property NbEventLogs() As Integer
            Get
                Return _NbEventLogs
            End Get
            Set(ByVal value As Integer)
                _NbEventLogs = value
            End Set
        End Property


        '<Category("MetaData")> _
        '<IsReadOnly(True)> _
        'Public Property LastLogTime() As DateTime
        '    Get
        '        Return _LastLogTime
        '    End Get
        '    Set(ByVal value As DateTime)
        '        _LastLogTime = value
        '    End Set
        'End Property


        <ExtendedCategory("MetaData")> _
        Public ReadOnly Property NbKeys() As Integer
            Get
                Return Me._StatsByKey.Count
            End Get
        End Property

        <ExtendedCategory("MetaData")> _
            <IsReadOnly(True)> _
            <Editor(GetType(PropertyEditorEditControl), GetType(EditControl))> _
            <LabelMode(LabelMode.Top)> _
        Public Property ComputationTime() As STimeSpan
            Get
                Return _ComputationTime
            End Get
            Set(ByVal value As STimeSpan)
                _ComputationTime = value
            End Set
        End Property

        <ExtendedCategory("OverallStats")> _
            <IsReadOnly(True)> _
            <Editor(GetType(PropertyEditorEditControl), GetType(EditControl))> _
            <LabelMode(LabelMode.Top)> _
        Public Property AverageKeyStatistics() As CacheKeyStatistics
            Get
                Return _AverageKeyStatistics
            End Get
            Set(ByVal value As CacheKeyStatistics)
                _AverageKeyStatistics = value
            End Set
        End Property

        <ExtendedCategory("OverallStats")> _
            <IsReadOnly(True)> _
            <Editor(GetType(DictionaryEditControl), GetType(EditControl))> _
            <CollectionEditor(True, False, True, False, 5)> _
            <LabelMode(LabelMode.Top)> _
        Public ReadOnly Property KeysByDiagnostic() As SerializableDictionary(Of CacheDistributionType, String)
            Get
                Dim toReturn As New SerializableDictionary(Of CacheDistributionType, String)
                Dim tempDico As New Dictionary(Of CacheDistributionType, List(Of String))

                Dim tempKeys As List(Of String) = Nothing
                Dim tempDistributionType As CacheDistributionType
                For Each keyStat As KeyValuePair(Of String, CacheKeyStatistics) In Me._StatsByKey
                    If keyStat.Value.Diagnostic.SortedDistributionTypes.Count = 0 _
                       OrElse (keyStat.Value.Diagnostic.SortedDistributionTypes.Count > 1 AndAlso keyStat.Value.Diagnostic.SortedDistributionTypes(0).DistributionType = CacheDistributionType.NotDistributed) Then
                        tempDistributionType = CacheDistributionType.Undefined
                    Else
                        tempDistributionType = keyStat.Value.Diagnostic.SortedDistributionTypes(0).DistributionType
                    End If
                    If Not tempDico.TryGetValue(tempDistributionType, tempKeys) Then
                        tempKeys = New List(Of String)
                    End If
                    tempKeys.Add(keyStat.Key)
                    tempDico(tempDistributionType) = tempKeys
                Next
                For Each objPair As KeyValuePair(Of CacheDistributionType, List(Of String)) In tempDico
                    tempKeys = New List(Of String)(objPair.Value)
                    tempKeys.Sort()
                    toReturn(objPair.Key) = CacheStrategy.FormatKeys(tempKeys.ToArray)
                Next
                Return toReturn
            End Get
        End Property

        <ExtendedCategory("SequenceGraph")> _
            <IsReadOnly(True)> _
            <Editor(GetType(GraphEditControl), GetType(EditControl))> _
            <LabelMode(LabelMode.Top)> _
        Public ReadOnly Property StatisticsGraph() As DistributedCachingGraph
            Get
                If _StatisticsGraph Is Nothing Then
                    _StatisticsGraph = New DistributedCachingGraph(False, Me._StatsByKey.Count)
                    For Each keyStat As KeyValuePair(Of String, CacheKeyStatistics) In Me._StatsByKey
                        Dim node As DistributedCachingNode = Me.GetNode(keyStat.Key)
                        Dim nodeInserted As Boolean
                        For Each nextK As KeyValuePair(Of String, Integer) In keyStat.Value.NextKeys
                            If nextK.Value > 1 AndAlso _StatsByKey.ContainsKey(nextK.Key) Then
                                If Convert.ToInt32(nextK.Value * 100 / keyStat.Value.NbNextKeys) > DistributedCachingProviderBase.Settings.StatisticsSettings.MinSequenceRatioForGraph Then
                                    Dim tag As New CacheSequenceTag(nextK.Value, _
                                                                    Convert.ToInt32((100 * nextK.Value / keyStat.Value.Diagnostic.UsualNextKey.TotalCount)), _
                                                                    keyStat.Value.Diagnostic.UsualNextKey.Key = nextK.Key)
                                    _StatisticsGraph.AddVerticesAndEdge(New DistributedCachingEdge(node, Me.GetNode(nextK.Key), tag))
                                    nodeInserted = True
                                End If
                            End If
                        Next
                        If Not nodeInserted Then
                            _StatisticsGraph.AddVertex(node)
                        End If
                    Next
                End If
                Return _StatisticsGraph
            End Get
            'Set(ByVal value As BidirectionalGraph(Of TargetNode, CacheKeyStatisticsEdge))
            '    Me._StatisticsGraph = value
            'End Set
        End Property

        <ExtendedCategory("IndividualKeyStats")> _
            <Editor(GetType(DictionaryEditControl), GetType(EditControl))> _
            <KeyEditor(GetType(CustomTextEditControl))> _
            <ValueEditor(GetType(PropertyEditorEditControl))> _
            <CollectionEditor(True, False, True, True, 20)> _
            <LabelMode(LabelMode.Top)> _
        Public Property StatsByKey() As SerializableDictionary(Of String, CacheKeyStatistics)
            Get
                Return _StatsByKey
            End Get
            Set(ByVal value As SerializableDictionary(Of String, CacheKeyStatistics))
                _StatsByKey = value
            End Set
        End Property


        Private _tempNodes As New Dictionary(Of String, DistributedCachingNode)

        Public Function GetNode(ByVal key As String) As DistributedCachingNode
            Dim toReturn As DistributedCachingNode = Nothing
            If Not Me._tempNodes.TryGetValue(key, toReturn) Then
                toReturn = New DistributedCachingNode(Me._StatsByKey(key))
                Me._tempNodes(key) = toReturn
            End If
            Return toReturn
        End Function

    End Class
End Namespace